﻿// See https://aka.ms/new-console-template for more information
//享元模式
//当系统中存在大量相同或相似的对象时，我们就可以考虑使用享元模式。享元模式通过共享技术实现或者相似的细粒度对象的复用，从而节约内存空间，提高系统性能。在享元模式中会提供一个享元池用于存储已经创建好的享元对象。
//享元模式的核心思想是将对象分为两部分，其中一部分包含了对象的内部状态（intrinsic state），另一部分包含了对象的外部状态（extrinsic state）。内部状态是可以共享的。而外部状态则是不可以共享的，每个对象都需要独立维护。通过共享内部状态，可以大幅减少内存使用和对象创建的数量，提高程序的性能和效率。
//享元模式由一下几个部分组成：
//·Flyweight（享元）：定义了享元对象的接口，其中包含了设置和获取内部状态的方法。
//·ConcreteFlyweight（具体享元）：实现了享元接口，包含了内部状态和外部状态，可以被共享和重复使用。
//·UnsharedConcreteFlyweight（非共享具体享元）：与具体享元类似，但是不可以被共享和重复使用。
//·FlyweightFactory（享元工厂）：负责维护和管理享元对象，以确保每个对象只被创建一次。在客户端请求一个享元对象时，享元工厂会检查对象池中是否已经存在该对象，如果存在则直接返回，否则创建新的对象并假如对象池中。
//·Client（客户端）：通过享元工厂来获取和使用享元对象，客户端通常需要提供外部状态参数。

using System.Drawing;

//创建享元工厂
CharacterFactory CharacterFactory = new CharacterFactory();

//创建外部状态
Color color = Color.Red;

//创建字符并设置颜色
ICharacter character1 = CharacterFactory.GetCharacter('A', 10, 20, new byte[] { 1, 2, 3 });
character1.SetColor(color);
ICharacter character2 = CharacterFactory.GetCharacter('B', 15, 25, new byte[] { 4, 5, 6 });
character2.SetColor(color);
ICharacter character3 = CharacterFactory.GetCharacter('A', 10, 25, new byte[] { 1, 2, 5 });
character3.SetColor(color);

//显示字符
character1.Display(12);
character2.Display(16);
character3.Display(14);

//下面是一个基于享元模式的简单示例，用于演示如何在文本编辑器中使用相同的字体和颜色创建多个字符，该示例中，每个字符对象包含了内部状态（即字形和大小）和外部状态（即颜色），其中字形和大小何以被多个字符对象共享，而颜色则是独立的，每个字符对象都需要独立维护。

//定义享元接口
public interface ICharacter
{
    void SetColor(Color color);

    void Display(int fontSize);
}

//具体享元类
public class Character : ICharacter
{
    //内部状态
    private char symbool;

    private int width;
    private int height;
    private byte[] fontData;//假设字形数据很大，需要通过共享来节省内存

    //外部状态
    private Color color;

    public Character(char symbool, int width, int height, byte[] fontData)
    {
        this.symbool = symbool;
        this.width = width;
        this.height = height;
        this.fontData = fontData;
    }

    public void SetColor(Color color)
    {
        this.color = color;
    }

    public void Display(int fontSize)
    {
        Console.WriteLine("Symbol:{0},Width:{1},Height:{2},FontSize:{3},Color:{4}", symbool, width, height, fontSize, color);
    }
}

//享元工厂
public class CharacterFactory
{
    private Dictionary<char, ICharacter> characters = new Dictionary<char, ICharacter>();

    public ICharacter GetCharacter(char symbool, int width, int height, byte[] fontData)
    {
        //此处的处理便是享元工厂中相同的对象只有一个
        if (characters.ContainsKey(symbool))
        {
            return characters[symbool];
        }
        else
        {
            ICharacter character = new Character(symbool, width, height, fontData);
            characters[symbool] = character;
            return character;
        }
    }
}